package com.wtwd.campus.utils;

import com.alibaba.fastjson.JSONObject;
import com.wtwd.campus.constant.OrgTypeEnum;
import com.wtwd.campus.constant.SignConstant;
import com.wtwd.campus.model.vo.TreeNode;
import com.wtwd.campus.model.vo.TreeVO;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author zdl
 * @Description
 * @create 2021-06-17 16:36
 */
public class TreeUtil {
    /**
     * * 生成树
     * * 1.转换树节点对象并且将数据以pid为key,该父类子节点集合为值 放入Map
     * * 2.遍历Map中每个节点数据,设置节点的子节点,并找出被使用的子节点
     * * 3.找出Map中未使用过的子节点则这些节点为顶级节点
     *
     * @param treeData
     * @return
     */
    public static List<? extends TreeVO> createTree(List<? extends TreeVO> treeData) {
        if (treeData == null || treeData.size() == 0) {
            return null;
        }
        Map<Integer, List<TreeVO>> childMap = treeData.stream().collect(Collectors.groupingBy(data -> data.getPid()));
        List<Integer> usePid = new ArrayList<>(treeData.size());
        childMap.forEach((key, value) -> {
            value.forEach(data -> {
                data.setChildren(childMap.get(data.getId()));
                usePid.add(data.getId());
            });
        });
        List<Integer> noUsePids = new ArrayList<>(childMap.size());
        for (Integer pid : childMap.keySet()) {
            if (!usePid.contains(pid)) {
                noUsePids.add(pid);
            }
        }
        List<TreeVO> treeList = childMap.get(noUsePids.get(0));
        for (int i = 1; i < noUsePids.size(); i++) {
            treeList.addAll(childMap.get(noUsePids.get(i)));
        }
        return treeList;

    }

    public static void main(String[] args) {
        TreeNode t1 = new TreeNode(100000, "大中华", 0);
        TreeNode t3 = new TreeNode(101000, "江苏省", 100000);
        TreeNode t2 = new TreeNode(102000, "广东省", 100000);
        TreeNode t4 = new TreeNode(102010, "深圳市", 102000);
        TreeNode t5 = new TreeNode(102020, "广州市", 102000);
        TreeNode t6 = new TreeNode(101010, "南京市", 101000);
        TreeNode t7 = new TreeNode(102021, "宝安区", 102010);
        TreeNode t8 = new TreeNode(102022, "南山区", 102010);
        ArrayList<TreeNode> tt = new ArrayList<>(8);
        tt.add(t1);
        tt.add(t2);
        tt.add(t3);
        tt.add(t4);
        tt.add(t5);
        tt.add(t6);
        tt.add(t7);
        tt.add(t8);
        for (TreeNode t : tt) {
            System.out.println(t);
        }

        System.out.println(JSONObject.toJSONString(buildTree(tt), true));
    }

    //利用key-value数据结构实现无限层级树的构建
    public static TreeNode buildTree(List<TreeNode> treeData) {
        Map<Integer, List<TreeNode>> childMap = new HashMap<>();
        //TODO 1.遍历所有节点数据，以节点父ID(pid)为key,相同父ID的节点集合为value构建数据。
        for (TreeNode node : treeData) {
            Integer pid = node.getPid();
            List<TreeNode> childNodes = childMap.get(pid);
            if (childNodes == null) {
                childNodes = new ArrayList<>();
                childMap.put(pid, childNodes);
            }
            childNodes.add(node);
        }
        //TODO 2.再次遍历所有节点数据，以本节点ID为key,获取本节点的孩子节点集合，并设置为本节点的孩子节点。
        for (Map.Entry<Integer, List<TreeNode>> entry : childMap.entrySet()) {
            for (TreeNode node : entry.getValue()) {
                Integer nodeId = node.getId();
                node.setChildren(childMap.get(nodeId));
            }
        }
        //TODO 3.以0(0为根节点默认父ID)key 获取根节点集合，获取集合中的第一个元素及为树的根节点，至此该根节点包含整个树形结构数据。
        return childMap.get(0).get(0);
    }

    /**
     * 通过节点类型组合PiD生成树
     * 避免各个节点来自不同模块导致pid冲突
     *
     * @param treeData
     * @return
     */
    public static List<? extends TreeVO> createTreeByType(List<? extends TreeVO> treeData) {
        if (treeData == null || treeData.size() == 0) {
            return null;
        }
        Map<String, List<TreeVO>> childMap = treeData.stream().collect(Collectors.groupingBy(data -> StringUtils.joinWith(SignConstant.DELIMITER, data.getType(), data.getPid())));
        List<String> usePid = new ArrayList<>(treeData.size());
        childMap.forEach((key, value) -> {
            for (TreeVO data : value) {
                String type = data.getType();//节点类型
                // 获取下一层级孩子节点
                String childKey = StringUtils.joinWith(SignConstant.DELIMITER, Integer.parseInt(type) + 1, data.getId());
                List<TreeVO> treeVOS1 = childMap.get(childKey);
                //获取同一层级孩子节点,当自身ID,与父模块ID不相等,可获取同级孩子节点
                List<TreeVO> treeVOS = null;
                if (data.getType().equals(OrgTypeEnum.ORG.getType()) &&!data.getId().equals(data.getPid())) {
                    treeVOS = childMap.get(StringUtils.joinWith(SignConstant.DELIMITER, type, data.getId()));
                }
                if (treeVOS != null) {
                    if (treeVOS1 != null) {
                        ArrayList<TreeVO> childs = new ArrayList<>();
                        childs.addAll(treeVOS1);
                        childs.addAll(treeVOS);
                        treeVOS1 = childs;
                    } else {
                        treeVOS1 = treeVOS;
                    }
                    usePid.add(StringUtils.joinWith(SignConstant.DELIMITER, type, data.getId()));
                }
                data.setChildren(treeVOS1);
                usePid.add(childKey);
            }
        });

        List<String> noUsePids = new ArrayList<>(childMap.size());
        for (String pid : childMap.keySet()) {
            if (!usePid.contains(pid)) {
                noUsePids.add(pid);
            }
        }
        List<TreeVO> treeList = childMap.get(noUsePids.get(0));
        for (int i = 1; i < noUsePids.size(); i++) {
            treeList.addAll(childMap.get(noUsePids.get(i)));
        }
        return treeList;

    }

}
